package se.statifyme.client.declaration;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import se.thoka.twt.client.form.TWTFormField;
import se.thoka.twt.client.utils.validation.DateTimeValidation;
import se.thoka.twt.client.utils.validation.DoubleValidation;
import se.thoka.twt.client.utils.validation.IntegerValidation;
import se.thoka.twt.client.utils.validation.NotEmptyValidation;
import se.thoka.twt.client.widgets.TWTTextBox;

public class FieldUtil {
	
	private interface HasAcceptClasses {
		Class<?>[] getClasses();
	}

	private enum FieldCreator implements HasAcceptClasses{
		STRING(String.class, Date.class, Integer.class, int.class, Double.class, double.class) {
			@Override
			public TWTFormField<?> createField(GWTItemFieldDeclaration fieldDeclaration) {
				return new TWTTextBox(fieldDeclaration.getId(), fieldDeclaration.getDisplayName());
			}
		},
		;
		private final Class<?>[] classes;
		private FieldCreator(Class<?>... classes) {
			this.classes = classes;
		}
		
		@Override
		public Class<?>[] getClasses() {
			return classes;
		}
		
		public abstract TWTFormField<?> createField(GWTItemFieldDeclaration fieldDeclaration);
	}
	
	private enum FieldValidation implements HasAcceptClasses {
		DATE(Date.class) {
			@Override
			public void addValidations(TWTFormField<?> field) {
				field.addValidation(new DateTimeValidation(true));
			}
		},
		DOUBLE(Double.class, double.class) {
			@Override
			public void addValidations(TWTFormField<?> field) {
				field.addValidation(DoubleValidation.INSTANCE_NOT_NULL);
			}
		},
		INTEGER(Integer.class, int.class) {
			@Override
			public void addValidations(TWTFormField<?> field) {
				field.addValidation(IntegerValidation.INSTANCE_NOT_NULL);
			}
		},
		;
		private final Class<?>[] classes;
		private FieldValidation(Class<?>... classes) {
			this.classes = classes;
		}
		
		public abstract void addValidations(TWTFormField<?> field);
		@Override
		public Class<?>[] getClasses() {
			return classes;
		}
	}
	
	
	public static TWTFormField<?> createFieldForType(GWTItemFieldDeclaration fieldDeclaration) {
		String id = fieldDeclaration.getId();
		String typeClassname = fieldDeclaration.getType();
		List<FieldCreator> types = getByClassname(FieldCreator.values(), typeClassname );
		if (types.isEmpty()) {
			throw new IllegalArgumentException("Unsupported field type: " + typeClassname + " for ID '" + id + "'");
		}
		TWTFormField<?> result = types.get(0).createField(fieldDeclaration);
		List<FieldValidation> fieldValidations = getByClassname(FieldValidation.values(), typeClassname);
		for (FieldValidation validation : fieldValidations) {
			validation.addValidations(result);
		}
		if (!fieldDeclaration.isOptional()) {
			result.addValidation(NotEmptyValidation.INSTANCE);
		}
		
		return result;
	}
	
	private static <T extends HasAcceptClasses>List<T> getByClassname(T[] ts, String classname) {
		List<T> result = new ArrayList<T>();
		for (T t : ts) {
			Class<?>[] classes = t.getClasses();
			for (Class<?> clazz : classes) {
				if (clazz.getName().equals(classname)) {
					result.add(t);
				}
			}
		}
		return result;
	}
	
}
